﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SIA.Configurators;

namespace SIA.HwAccess.PLCSiemens
{
    public class S7Boolean : S7Signal, IDigitalSignal
    {
        // Eventi
        public override event SignalEvent ValueChange;
        public event SignalEvent RisePositiveFront;
        public event SignalEvent RiseNegativeFront;

        //Dati
        private Boolean _value;
        public override object Value { get { return DigitalValue; } set { DigitalValue = (Boolean)value; } }
        public Boolean DigitalValue { get { return _value; } set {

            //Verifica presenza del byte da leggere
            if ((!_connection.RawData.ContainsKey(_address.DataKey)) || (Connection.RawData[_address.DataKey].Length  < _address.StartByte))
            {
                SIA.Messages.MessageManager.sendMessage(this, "SET Boolean: Dati non presenti nella connessione", SIA.Messages.eMessageType.DEBUG);
                return;
            }

            //Appoggio per eventi 
            Boolean oldValue = _value;
            _value = value;

            // Mi assicuro di scrivere sempre nell'area dati 
            if (_value)
                _connection.requestWriteData(_address, 0, (Byte)(_connection.RawData[_address.DataKey][_address.StartByte] | (Byte)(1 << _address.Bit)));
            else
                _connection.requestWriteData(_address, 0, (Byte)(_connection.RawData[_address.DataKey][_address.StartByte] & ~((Byte)(1 << _address.Bit))));


            //Controllo eventi
            if (_value!=oldValue)
                evaluateEvent(oldValue, _value);

        } }

        /// <summary>Costruttore Generico</summary>
        /// <param name="signalProperty"></param>
        /// <param name="connection"></param>
        public S7Boolean(IDictionaryProperty signalProperty, IHwConnection connection)
            : base(signalProperty, connection)
        {
            _connection.DataArrived += new ConnectionDataEvent(_connection_DataArrived);
        }

        /// <summary>Gestine Evento DataArrived. Aggiorno il valore del segnale e valuto gli eventi</summary>
        /// <param name="conn">Connessione di origine</param>
        /// <param name="data">Nuovi dati arrivati</param>
        void _connection_DataArrived(IHwConnection conn, IRawData data)
        {
            if (data.ContainsKey(_address.DataKey))
            {
                Boolean oldValue = _value;
                _value = (data[_address.DataKey][_address.StartByte] & (byte)(1 << _address.Bit)) > 0;
                evaluateEvent(oldValue, _value);
            }
            else
                SIA.Messages.MessageManager.sendMessage(this, "Dati non presenti nella connessione", SIA.Messages.eMessageType.DEBUG);
        }
        

        /// <summary>Controllo della presenza di eventi</summary>
        /// <param name="oldValue"></param>
        /// <param name="newValue"></param>
        private void evaluateEvent(Boolean oldValue, Boolean newValue)
        {
            if (oldValue != newValue)
                if (this.ValueChange != null) this.ValueChange(this);
            if (oldValue == true && newValue == false)
                if (this.RiseNegativeFront != null) this.RiseNegativeFront(this);
            if (oldValue == false && newValue == true)
                if (this.RisePositiveFront != null) this.RisePositiveFront(this);
        }

    }
}
